#![feature(split_array)]
/**
* 注意夜更版本注释，必须放在文件最前面
* 数组类型要求所有的元素同一个类型
* 数组实现了以下特质：
   Copy
   Clone
   Debug
   IntoIterator (implemented for [T; N], &[T; N] and &mut [T; N])
   PartialEq, PartialOrd, Eq, Ord
   Hash
   AsRef, AsMut
   Borrow, BorrowMut
   --
*/
#[derive(Debug)]
struct Student{
    id: u32,
    score: u32
}
fn main() {
    test_def_and_access();
    test_eacg();
    test_map();
    test_split();
    test_sort();
    test_reverse();
    test_convert();
    test_agg();
    //此外还有一些值得关注的函数
    // concat() 用于合并多个数组为一个新的对象
    // connect(s) 使用特定连接符连接数组（实为插入中中间)
    // contain(&t)  判断是否包含一个元素
    // swap(a, b) 交换两个元素的位置

}

fn test_def_and_access() {
    //1.0 定义数组
    //最常见的是列出数组的类型和长度，然后初始化每个元素
    let arr1: [i32; 5] = [1, 2, 3, 4, 5];
    //或者使用初始化表达式[T;N] ,要求T是常量或者是实现了Copy特质的数据类型
    const FOOD: usize = 5; // 常量
    let arr2 = [FOOD; 5]; // 所有元素都是0的数组
    let arr3 = [0; 5]; // 所有元素都是0的数组
    println!("{:?}", arr1);
    println!("{:?}", arr2);
    println!("{:?}", arr3);

    //2.0 访问数组中的元素
    //数组的访问方式有多种，比如：通过索引访问、通过迭代器遍历等。

    //2.1 通过索引访问 T[N] 索引从0开始，到N-1结束,或者get(N)
    let first_element = arr1[0];
    println!("第一个元素是 {}", first_element);
    let second_element = arr1.get(1).unwrap();
    println!("第二个元素是 {}", second_element);
    //2.2 通过迭代器遍历：
    //也可以通过迭代器遍历数组中的元素：
    //`for element in &arr1` 是语法糖，会调用`arr1.into_iter()`返回不可变引用迭代器
    for element in &arr1 {
        println!("{}", element);
    }

    //2.3 通过切片访问：
    //还可以通过切片访问数组中的一部分元素：
    let slice = &arr1[0..3]; // 获取前三个元素的切片
    println!("{:?}", slice);

    //2.4 通过迭代器
    //`arr1.iter()` 显式调用，也返回不可变引用迭代器
    //两种方式功能相同，但`&arr1`更简洁，是推荐用法
    for element in arr1.iter() {
        println!("{}", element);
    }
}

/**
 * 测试函数each_mut()的使用  each_mut(&mut self) -> [&mut T; N]
 * 还有一个each_ref()函数，  each_ref(&self) -> [&T; N]
 * 不能说这两个方法没有什么用，在某些情况下还是有用的。比如在你想遍历数组但不希望修改其内容时，
 * 可以使用each_ref()方法返回一个不可变引用迭代器。
 * 而在你需要对数组中的元素进行修改时，则可以使用each_mut()方法返回一个可变引用迭代器。
 */
fn test_eacg() {
    let mut girls = [
        "black-haired".to_string(),
        "blonde".to_string(),
        "brown-haired".to_string(),
    ];
    girls[0] = "lml".to_string();
    println!("{:?}", girls);
    for girl in girls.iter_mut() {
        girl.push_str(" 中国");
    }
    println!("{:?}", girls);

    for girl in girls.each_mut().iter_mut() {
        girl.push_str(" 中国");
    }
    println!("{:?}", girls);
}

/**
 * 这是一个有意思的函数
 * pub fn map<F, U>(self, f: F) -> [U; N] where F: FnMut(T) -> U,
 * 利用一个实现了FnMut特质（即实现了调用自身的方法）的函数f，将数组中的每个元素都转换成了U类型的新数组。
 *
 * 关于map的重要说明：
 * 1. map是惰性的，除非消费迭代器(如collect/for_each)，否则不会执行
 * 2. iter_mut().map()会返回新值，但不会修改原数组
 * 3. 要修改原数组，应该使用for_each或直接赋值
 */
#[allow(unused,unused_mut)]
fn test_map() {
    let mut scores = [10, 20, 30];
    let f = |x: i32| x * 2;

    // 示例1：map创建新数组
    let new_scores = scores.map(f);
    println!("map创建的新数组: {:?}", new_scores);
    println!("原数组未被修改: {:?}", scores);

    // 示例2：使用Iterator::map，可以创建一个可变的迭代器，但不直接修改原数组
    //Iterator::map 返回一个Map(std::iter::Map)
    let f1=|x: &i32| {2*x};
    let mut bb = scores.iter().map(f1);  //|x:&i32| *x*2
    for x in bb {
        println!("{}", x);
    }
    println!("iter_mut().map()后数组未变: {:?}", scores);

    // 示例3：正确修改数组的方法
    // 方法1：使用for_each消费迭代器
    scores.iter_mut().for_each(|x| *x *= 2);
    println!("使用for_each后: {:?}", scores);

    let a = [1, 2, 3];
    let mut iter = a.iter().map(|x| 2 * x);
    println!("{:?}", iter.next()); // 2

    println!("{:?}", a); // 4
}

/**
 * 测试切割数组 
 * split_array_ref-这是nightly特性，在稳定版中不可用
 * split_at -- 这是稳定版特性.返回两个数组引用
 * split_at_mut -- 这是稳定版特性.返回两个数组可变引用,原来的被消耗调了，不可再用

 */
fn  test_split(){
    let  mut v = [10,1, 2, 3, 4, 5, 6];
    let (left, right) = v.split_array_ref::<3>();
    println!("{:?}被切割后， left={:?},right={:?}",v,left,right); // [1]

    let (left, right) = v.split_at(3); // 稳定版特性
    println!("{:?}被切割后， left={:?},right={:?}",v,left,right); // [1]
    //left[0]=10; // 报错，left是只读引用
    let mut p=[1100,10,-10,-2,933,83,222];
    let (a, b) = p.split_at_mut(3); // 稳定版特性
    a[0]=1039; 
    println!("left={:?},right={:?}",a,b); // [1]
    //assert_eq!(v, [1, 2, 3, 4, 5, 6,9]);
}

/**
 * 测试排序
 * 有多个方法:
 * sort()  -- 默认升序
 * sort_by(f)  -- 自定义排序规则(通常是升序或者降序) ,f通常返回true，false
 * sort_by_key(f)  -- 按键排序，f返回排序的键值，可以自定以规则
 * 
 * 判断数组是否排序
 * is_sorted()  -- 判断数组是否已经排序(升序)
 * is_sorted_by(f)  -- 判断数组是否已经排序，根据自定义的规则
 * is_sorted_by_key(f)  -- 按键判断数组是否已经排序，根据自定义的规则
 */
fn test_sort(){
    let mut v = [10i32,1, 2, -3, -4, 5, 6];
    v.sort_by(|a, b| a.cmp(b)); // 升序排序    
    println!("{:?} is {}", v,v.is_sorted()); // [1, 2, 3, 4, 5, 6, 10]
    v.sort_by(|a, b| b.cmp(a)); // 降序排序
    println!("{:?} is {}", v,v.is_sorted()); // [10, 6, 5, 4, 3, 2, 1]
    v.sort_by_key(|x| *x); // 按值排序
    println!("{:?}", v); // [1, 2, 3, 4, 5, 6, 10]
    v.sort_by_key(|x| -*x); // 按值降序排序
    println!("{:?}", v); // [10, 6, 5, 4, 3, 2, 1]
    v.sort_by_key(|x| x.abs()); // 绝对值排序
    println!("{:?}", v); // [1, 2, 3, 4, 5, 6, -10]

    //构建一个Student数组
    let ma=Student{id:101,score:87};
    let lu=Student{id:102,score:99};
    let hu=Student{id:103,score:95};

    let mut  stu = [ma,lu,hu]; // 构建一个Student数组
    stu.sort_by_key(|x| x.score); // 按分数排序
    println!("{:?}", stu); // 

}

/**
 * 测试反转
 */
fn test_reverse(){
    let mut v = [1, 2, 3];
    v.reverse();
    println!("{:?}", v); // [3, 2, 1]
}

/**
 * 测试基本的聚合操作，比如求和、最大值等
 */
fn test_agg(){
   //求数组的最大值，最小值，平均值
    let v = [1, 2, 3];
    let sum: i32 = v.iter().sum(); // 求和
    println!("Sum: {}", sum); // Sum: 6
    let max = *v.iter().max().unwrap(); // 求最大值，需要解引用
    println!("Max: {}", max); // Max: 3
    let min = *v.iter().min().unwrap(); // 求最小值，需要解引用
    println!("Min: {}", min); // Min: 1
    let avg: f64 = v.iter().map(|&x| x as f64).sum::<f64>() / v.len() as f64; // 求平均值
    println!("Avg: {}", avg); // Avg: 2.0
}

fn test_convert(){
    let v = [1, 2, 3];
    // 转成Vec<i32>
    let vec: Vec<i32> = v.to_vec();
    println!("{:?}", vec); // [1, 2, 3]

    // 转成&[i32]
    let slice: &[i32] = &v;
    println!("{:?}", slice); // [1, 2, 3]
}